package timit;

import java.io.*;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.*;

/**
 * Created with IntelliJ IDEA.
 * User: lahiru
 * Date: 6/13/14
 * Time: 10:03 AM
 * To change this template use File | Settings | File Templates.
 */
public class HUSpeakerDist {
    private static final int numberOfLayers = 1;
    private static final String hiddenActivationDir = "/media/Lahiru/Research/speaker-sensitivity/si_model/activations/";
    private static final String pdfAlignmentsDir = "/home/lahiru/experiments/Speaker-effects/mono_dnn_23/alignments/";
//    private static final String saveObjects = "/home/lahiru/experiments/Speaker-effects/objects/train/";
//    private static final String listOfSpeakers = "FALK0 FALR0 FBCG1 FBCH0 FBJL0 FCDR1 FCEG0 FCKE0 FCMM0 FDFB0 MCAE0 " +
//            "MCAL0 MCHL0 MCSS0 MCTH0 MCTM0 MDBP0 MDCD0 MDHS0 MDLC2";
//        private static final String listOfSpeakers = "FCAL1 FDMS0 MBNS0 MRTK0";
        private static final String listOfSpeakers = "4at 4au 4av 4af 4ag 4ah 4ai 4aw 4ax 4ay";
    private static final int numberOfHiddenUnits=2048;
//    private static final int pdfCount = 117;
    private static final String haVectorDirectory = "/media/Lahiru/Research/speaker-sensitivity/si_model/vectors/";
    private static final String datDirectory = "/media/Lahiru/Research/speaker-sensitivity/si_model/dats/";

    public static void main(String[] args) {
        List<String> speakers = (Arrays.asList(listOfSpeakers.split(" ")));
        int numSpeakers = speakers.size();


        for (int i = 1; i <= numberOfLayers; i++) {
            System.out.println(" Start processing the layer " + i);

            Map<Integer,Integer> spkCountMap = new HashMap<Integer, Integer>(numSpeakers);
            for(int j=0; j<numSpeakers; j++){  //initialize the scounts map
                spkCountMap.put(j,0);
            }

            Map<Integer,List<Double>> huMap = new HashMap<Integer, List<Double>>(numberOfHiddenUnits);
            for(int j=0; j<numberOfHiddenUnits; j++){
                List<Double> tempList = new ArrayList<Double>(numSpeakers);
                for(int k=0; k<numSpeakers; k++){
                    tempList.add(0.0);
                }
                huMap.put(j,tempList);
            }

            int totalFrameCount = 0;
            int speakerId=0;
            for(String spk:speakers){
                int finalFrameCount = 0;

                String ha = hiddenActivationDir + "h" + i + "/activations_" + spk + ".ark";
//                System.out.println(" Reading the activation file  " + ha + " for the speaker " + spk);
                //Read pdf-alignments line by line, file contains a line per utterance.

                try {
                    BufferedReader haBr = new BufferedReader(new FileReader(ha));
                    String line1;

                    int utteranceCount = 0;
                    int frameCount = 0;
                    String frameUtterance = "";
                    String utterance = "";

                        while ((line1 = haBr.readLine()) != null) {

                            String hArray[] = line1.trim().split(" ");

                            if (hArray.length == 3) {  //starting of an utterance
                                utteranceCount = utteranceCount + 1;
                                frameCount = 0;
                                frameUtterance = hArray[0];

                                String tempArray[] = null;
                                String line2 = "";

                                if (!frameUtterance.equalsIgnoreCase(utterance)) {
//                                    System.err.println("The frame utterance " + frameUtterance);
//                                    System.err.println("The phone utterance " + utterance);

                                    do {
                                        line2 = haBr.readLine();
                                        tempArray = line2.trim().split(" ");

                                    } while (tempArray.length != 3);

//                                    System.err.println("The new frame utterance is " + tempArray[0]);
                                    //write about attributes

                                }

                            } else if (hArray.length == numberOfHiddenUnits) {  //intermediate frame
//                                int pdfId = Integer.parseInt(phoneIds[frameCount + 1]);
                                spkCountMap.put(speakerId, spkCountMap.get(speakerId)+1);


                                for(int p=0; p<numberOfHiddenUnits;p++){
//                                for(int p=0; p<1;p++){
                                    List<Double> tmpList = huMap.get(p);
                                    tmpList.add(speakerId, tmpList.remove(speakerId)+Double.parseDouble(hArray[p]));
                                    huMap.put(p,tmpList);
                                }

//                                speaker.addFrameStats(Integer.parseInt(phoneIds[frameCount + 1]), hArray);
                                frameCount = frameCount + 1;
                            } else if (hArray.length == numberOfHiddenUnits + 1) {   //last frame of the utterance

                                spkCountMap.put(speakerId, spkCountMap.get(speakerId)+1);

                                for(int p=0; p<numberOfHiddenUnits;p++){
//                                for(int p=0; p<1;p++){
                                    List<Double> tmpList = huMap.get(p);
                                    tmpList.add(speakerId, tmpList.remove(speakerId)+Double.parseDouble(hArray[p]));
                                    huMap.put(p,tmpList);
                                }

//                                speaker.addFrameStats(Integer.parseInt(phoneIds[frameCount + 1]), Arrays.copyOfRange(hArray, 0, hArray.length - 1));
                                frameCount = frameCount + 1;
                                finalFrameCount = finalFrameCount + frameCount;
                                break;
                            } else {
                                System.err.println("This is not possible " + hArray.length);
                            }
                        }
//                    }
                    haBr.close();
                    totalFrameCount = totalFrameCount + finalFrameCount;
                    speakerId = speakerId + 1;
                } catch (IOException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }
            }


            try {
                FileWriter fileWriter = new FileWriter(haVectorDirectory + i + ".dat");
                BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);

//                bufferedWriter.write("@relation hiddenUnits");
//                bufferedWriter.newLine();
//                bufferedWriter.newLine();
//
//                for (int h = 0; h < numSpeakers; h++) {
//                    bufferedWriter.write("@attribute spk" + h + " numeric\n");
//                }
//                bufferedWriter.newLine();
//                bufferedWriter.newLine();
//
//                bufferedWriter.write("@data\n");
//                bufferedWriter.newLine();
//                bufferedWriter.newLine();
                double totalDistance = 0.0;
                for (int j=0; j<numberOfHiddenUnits; j++){
//                for (int j=0; j<1; j++){

                    FileWriter fileWriter1 = new FileWriter(datDirectory+"h"+i+"/" + j + ".dat");
                    BufferedWriter bufferedWriter1 = new BufferedWriter(fileWriter1);

                    List<Double> tempList = huMap.get(j);
                    List<Double> activationVector = new ArrayList<Double>(numSpeakers);

//                    StringBuffer sb = new StringBuffer();
                    for (int p = 0; p < numSpeakers; p++) {
                        double value = tempList.get(p);
                        int count = spkCountMap.get(p);
//                        double finalvalue = (value/count);
                        NumberFormat formatter = new DecimalFormat("###.###############");
                        double intFinalVal = value/count;
                        String finalvalue = formatter.format(intFinalVal);
                        activationVector.add(intFinalVal);
//                        System.out.println("The value " + value);
//                        System.out.println("The pdf id " + p);
//                        System.out.println("The pdf count " + count);
//                        System.out.println("The finalValue " + finalvalue);
                        bufferedWriter1.write(finalvalue+"\n");
//                        if (p == numSpeakers - 1) {
//                            sb.append(finalvalue + "\n");
//                        } else {
//                            sb.append(finalvalue + ",");
//                        }
                    }
                    double distance = HUDist.calKLDistance(activationVector);
                    totalDistance = totalDistance + distance;
                    NumberFormat formatter = new DecimalFormat("###.###############");
                    bufferedWriter.write(formatter.format(distance)+"\n");
                    bufferedWriter1.close();

                }
                System.out.println("The total distance for layer " + i + " is " + totalDistance);
                bufferedWriter.close();
            } catch (IOException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }


        }


    }
}
